"use strict";
cc._RF.push(module, '3338ezj7YhArI3Gnx+vn8Q2', '_MsgSender');
// _MsgSender.js

"use strict";

// @import
var mod_GameMsgProtocol = require("./_GameMsgProtocol");

var mod_MsgRecognizer = require("./_MsgRecognizer");

var mod_Protobuf = require("./Lib/protobuf");
/**
 * WebSocket
 * 
 * @var {WebSocket}
 */


var g_oWebSocket = null; // @export

module.exports = {
  /** WebSocket 地址 */
  webSocketUrl: "",

  /**
   * 初始化
   * 
   * @param {string} strWebSocketUrl WebSocket 地址
   * @return
   */
  init: function init(strWebSocketUrl) {
    console.log("\u521D\u59CB\u5316\u6D88\u606F\u53D1\u9001\u8005, webSocketUrl = " + strWebSocketUrl);
    this.webSocketUrl = strWebSocketUrl;
  },

  /**
   * 是否已经断开连接
   * 
   * @return {boolean}
   */
  get isDisconnected() {
    return null == g_oWebSocket;
  },

  /**
   * 连接
   * 
   * @param {(bSuccezz: boolean) => void} funCb 回调函数
   * @return {void}
   */
  connect: function connect(funCb) {
    var _this = this;

    if (null != g_oWebSocket) {
      return;
    }

    console.log("尝试连接服务器"); // 创建 WebSocket

    var oWebSocket = new WebSocket(this.webSocketUrl);
    oWebSocket.binaryType = "arraybuffer";

    oWebSocket.onopen = function (oEvent) {
      console.log("\u5DF2\u8FDE\u63A5\u670D\u52A1\u5668, webSocketUrl = " + _this.webSocketUrl);
      g_oWebSocket = oWebSocket; // 确保回调函数不为空

      funCb = funCb || function () {}; // 执行回调函数


      funCb(true);
    };

    oWebSocket.onerror = function (oEvent) {
      console.error("\u8FDE\u63A5\u670D\u52A1\u5668\u5931\u8D25, webSocketUrl = " + _this.webSocketUrl);
      g_oWebSocket = null; // 确保回调函数不为空

      funCb = funCb || function () {}; // 执行回调函数


      funCb(false);
    };

    oWebSocket.onclose = function (oEvent) {
      console.warn("服务器连接已关闭");
      g_oWebSocket = null;
    };

    oWebSocket.onmessage = function (oEvent) {
      // 反序列化为消息对象
      var oMsg = __makeMsgObj(new Uint8Array(oEvent.data));

      if (!oMsg) {
        return;
      }

      console.log("\u4ECE\u670D\u52A1\u5668\u7AEF\u8FD4\u56DE\u6570\u636E, " + JSON.stringify(oMsg)); // 触发事件函数

      _this.onReceiveMsg(oMsg);
    };
  },

  /**
   * 发送消息
   * 
   * @param {{ msgCode: string, msgBody: any, }} oMsg 消息对象
   * @return {void}
   */
  sendMsg: function sendMsg(oMsg) {
    if (!oMsg || !g_oWebSocket) {
      return;
    } // 序列化为字节数组


    var oUint8Array = __makeUint8Array(oMsg);

    if (!oUint8Array || oUint8Array.byteLength <= 0) {
      return;
    } // 发送字节数组


    g_oWebSocket.send(oUint8Array);
  },

  /**
   * 接收消息对象
   * 
   * @param {{ msgCode: string, msgBody: any, }} oMsg 消息对象
   * @return {void}
   */
  onReceiveMsg: function onReceiveMsg(oMsg) {}
};
/**
 * 将消息对象序列化为字节数组
 * 
 * @param {{ msgCode: string, msgBody: any, }} oMsg 消息对象
 * @return {Uint8Array}
 */

function __makeUint8Array(oMsg) {
  if (!oMsg || !oMsg.msgCode || !oMsg.msgBody) {
    return null;
  } // 获取消息代码


  var strMsgCode = oMsg.msgCode;
  var nMsgCode = mod_GameMsgProtocol.msg.MsgCode[strMsgCode]; // 获取消息类型

  var strMsgType = mod_MsgRecognizer.recognize(nMsgCode);

  if (!strMsgType) {
    // 如果无法识别为消息类型,
    console.error("\u65E0\u6CD5\u8BC6\u522B\u4E3A\u6D88\u606F\u7C7B\u578B, msgCode = " + strMsgCode + " ( " + nMsgCode + " )");
    return null;
  } // 获取对应的 Protobuf 消息


  var oProtobufMsg = mod_GameMsgProtocol.msg[strMsgType];

  if (!oProtobufMsg) {
    // 如果对应的 Protobuf 消息为空,
    console.error("\u5BF9\u5E94\u7684 Protobuf \u6D88\u606F\u4E3A\u7A7A, strMsgType = " + strMsgType);
    return null;
  }

  var oWriter = mod_Protobuf.Writer.create(); // 先写出消息编号

  oWriter.uint32(nMsgCode >> 24 & 0xff);
  oWriter.uint32(nMsgCode >> 16 & 0xff);
  oWriter.uint32(nMsgCode >> 8 & 0xff);
  oWriter.uint32(nMsgCode & 0xff); // 将消息体序列化为二进制

  var oUint8Array = oProtobufMsg.encode(oMsg.msgBody, oWriter).finish();
  return oUint8Array;
}
/**
 * 将字节数组反序列化为消息对象
 * 
 * @param {Uint8Array} oUint8Array 字节数组
 * @return {{ msgCode: string, msgBody: any, }}
 */


function __makeMsgObj(oUint8Array) {
  if (!oUint8Array || !oUint8Array.byteLength) {
    return null;
  } // 获取消息代码


  var nMsgCode = (oUint8Array[0] & 0xFF) << 24 | (oUint8Array[1] & 0xFF) << 16 | (oUint8Array[2] & 0xFF) << 8 | oUint8Array[3] & 0xFF;
  var strMsgCode = mod_GameMsgProtocol.msg.MsgCode[nMsgCode]; // 获取消息类型

  var strMsgType = mod_MsgRecognizer.recognize(nMsgCode);

  if (!strMsgType) {
    // 如果无法识别为消息类型,
    console.error("\u65E0\u6CD5\u8BC6\u522B\u4E3A\u6D88\u606F\u7C7B\u578B, msgCode = " + strMsgCode + " ( " + nMsgCode + " )");
    return null;
  } // 获取对应的 Protobuf 消息


  var oProtobufMsg = mod_GameMsgProtocol.msg[strMsgType];

  if (!oProtobufMsg) {
    // 如果对应的 Protobuf 消息为空,
    console.error("\u5BF9\u5E94\u7684 Protobuf \u6D88\u606F\u4E3A\u7A7A, msgType = " + strMsgType);
    return null;
  } // 反序列化消息体


  var oMsgBody = oProtobufMsg.decode(oUint8Array.subarray(4));
  return {
    msgCode: strMsgCode,
    msgBody: oMsgBody
  };
}

cc._RF.pop();